package com.fanshuai.net.handler;

import com.fanshuai.config.ServerConfig;
import com.fanshuai.net.proxy.Proxy;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ProxyHandler extends SimpleChannelInboundHandler<Object> {
    private final Proxy proxy;

    public ProxyHandler(Proxy  proxy) {
        this.proxy = proxy;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        log.info("outbound channelActive, channel={}", ctx.channel());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        proxy.close();

        log.info("outbound channelInactive, channel={}", ctx.channel());
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof FullHttpRequest) {
            handleHttp(ctx, (FullHttpRequest) msg);
        }
        if (msg instanceof WebSocketFrame) {
            handleWebSocket(ctx, (WebSocketFrame) msg);
        }
    }

    private boolean isWebSocketRequest(FullHttpRequest request) {
        String connection = request.headers().get("Connection");
        String upgrade = request.headers().get("Upgrade");

        return connection.equalsIgnoreCase("Upgrade") && upgrade.equalsIgnoreCase("WebSocket");
    }

    private void handleHttp(ChannelHandlerContext ctx, FullHttpRequest request) {
        String uri = request.uri();
        if (isWebSocketRequest(request)) {
            //先建立proxy websocket连接
            proxy.webSocketHandshake(request.copy());

            //后与浏览器建立websocket连接
            String webSocketUrl = "ws://0.0.0.0:" + ServerConfig.serverPort + uri;
            WebSocketServerHandshaker handshaker = new WebSocketServerHandshakerFactory(webSocketUrl, null, false).newHandshaker(request);
            handshaker.handshake(ctx.channel(), request);
        } else {
            proxy.sendHttpRequest(request.copy());
        }
    }

    private void handleWebSocket(ChannelHandlerContext ctx, WebSocketFrame frame) {
        proxy.sendWebSocketFrame(frame.copy());
    }
}
